import numpy as np
from sklearn.model_selection import train_test_split
import sklearn.datasets as datasets
from sklearn.preprocessing import StandardScaler

class Classify:

    def __init__(self):
        self.all_ = None
        self.jieju_ = None
        self.xishu_ = None

    # 损失函数的 均方误差
    def J(self, x_b, y, theta):
        try:
            return np.sum((y - x_b.dot(theta)) ** 2) / len(y)
        except:
            return float('inf')

    def dJ(self, x_b, y, theta):
        # x_temp = np.vstack(np.ones(len(x), 1), x)
        # res = np.empty(x.shape[1])
        # res[0] = np.sum(x.dot(theta) - y)
        # for i in range(1, len(x)):
        #     res[i] = np.sum((x.dot(theta) - y) * x[:, i])
        # return res * 2 / len(x)
        return x_b.T.dot(x_b.dot(theta) - y) * 2. / len(x_b)

    def gradient_descent(self, x_b, y, initial_theta, eta, n_iters=1e4, epsilon=1e-8):
        theta = initial_theta
        iters = 0
        while iters < n_iters:
            last_theta = theta
            theta = theta - eta * self.dJ(x_b, y, theta)
            if abs(self.J(x_b, y, theta) - self.J(x_b, y, last_theta)) < epsilon:
                break
            iters += 1
        return theta

    def fit(self, x, y):
        x_b = np.hstack([np.ones((len(x), 1)), x])
        initial_theta = np.zeros(x_b.shape[1])
        initial_eta = 0.01
        theta = self.gradient_descent(x_b, y, initial_theta, initial_eta)
        self.jieju_ = theta[0]
        self.xishu_ = theta[1:]

    def predict(self, x):
        return np.array(x.dot(self.xishu_) + self.jieju_)

    def score(self, x_test, y_test):
        assert x_test.shape[0] == y_test.shape[0], \
            "位数不一样"
        y_predict = self.predict(x_test)
        return 1 - np.sum((y_predict - y_test) ** 2)/np.sum((y_test - np.mean(y_test)) ** 2)



boston = datasets.load_boston()
x_train, x_test, y_train, y_test = train_test_split(boston.data, boston.target, random_state=10)

ss =StandardScaler()
ss.fit(x_train)
x_train_standard = ss.transform(x_train)
x_test_standard = ss.transform(x_test)


cs = Classify()
cs.fit(x_train_standard,y_train)
print(cs.jieju_)
score = cs.score(x_test_standard, y_test)
print(score)


np.random.normal()